package com.jing.yao.modules.role.service.impl;

import com.jing.yao.code.UserCode;
import com.jing.yao.component.constants.BaseOperationEnum;
import com.jing.yao.component.mapper.YaoBaseMapper;
import com.jing.yao.constant.Enabled;
import com.jing.yao.exception.BusinessException;
import com.jing.yao.exception.BusinessExceptionBuilder;
import com.jing.yao.holder.UserContentHolder;
import com.jing.yao.modules.resource.dao.ResourceMapper;
import com.jing.yao.modules.resource.dao.RoleResourceMapper;
import com.jing.yao.modules.resource.dao.entity.ResourceEntity;
import com.jing.yao.modules.resource.dao.entity.RoleResourceEntity;
import com.jing.yao.modules.role.dao.RoleMapper;
import com.jing.yao.modules.role.dao.UserRoleMapper;
import com.jing.yao.modules.role.dao.entity.RoleEntity;
import com.jing.yao.modules.role.dao.entity.UserRoleEntity;
import com.jing.yao.modules.role.service.RoleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色相关service的实现类
 *
 * @author lirui
 * @since 2020-06-13
 */
@Service
public class RoleServiceImpl implements RoleService {

    /**
     * 角色相关
     */
    @Autowired
    private RoleMapper roleMapper;

    /**
     * 用户角色相关
     */
    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private ResourceMapper resourceMapper;

    @Autowired
    private RoleResourceMapper roleResourceMapper;

    @Override
    public YaoBaseMapper<RoleEntity> getMapper() {
        return roleMapper;
    }

    /**
     * 获取指定用户的角色
     *
     * @param username
     * @return
     */
    @Override
    public List<String> getUserRoles(String username) {
        LambdaQueryWrapper<UserRoleEntity> queryWrapper = Wrappers.<UserRoleEntity>lambdaQuery().eq(UserRoleEntity::getUsername, username);
        return userRoleMapper.selectList(queryWrapper)
                .stream()
                .map(userRoleEntity -> userRoleEntity.getRoleCode())
                .collect(Collectors.toList());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveRoleResource(String roleCode, List<String> resCodes) {
        //删除指定角色的资源
        roleResourceMapper.delete(Wrappers.<RoleResourceEntity>lambdaQuery().eq(RoleResourceEntity::getRoleCode, roleCode));
        //当资源为空时不做任何操作
        if (CollectionUtils.isEmpty(resCodes)) {
            return;
        }

        List<ResourceEntity> resourceEntities = resourceMapper.selectList(Wrappers.<ResourceEntity>lambdaQuery()
                .eq(ResourceEntity::getEnabled, Enabled.YES.getValue())
                .in(ResourceEntity::getResCode, resCodes));

        roleMapper.saveRoleResource(roleCode, resourceEntities, UserContentHolder.getContext().getUsername());
    }

    @Override
    public void processBeforeOperation(RoleEntity entity, BaseOperationEnum operationEnum) throws BusinessException {
        switch (operationEnum) {
            case INSERT:
                String roleCode = entity.getRoleCode();
                RoleEntity roleEntity = roleMapper.selectOne(Wrappers.<RoleEntity>lambdaQuery().eq(RoleEntity::getRoleCode, roleCode));
                if (roleEntity != null) {
                    throw BusinessExceptionBuilder.build(UserCode.ROLE_EXIST);
                }
                break;
        }
    }

    /**
     * 后置处理
     *
     * @param entity
     * @param operationEnum 操作类型
     * @throws BusinessException
     */
    @Override
    public void processAfterOperation(RoleEntity entity, BaseOperationEnum operationEnum) throws BusinessException {
        switch (operationEnum) {
            case DELETE:
                String roleCode = entity.getRoleCode();
                //删除角色对应的资源
                LambdaQueryWrapper<RoleResourceEntity> wrapper = Wrappers.<RoleResourceEntity>lambdaQuery()
                        .eq(RoleResourceEntity::getRoleCode, roleCode);
                roleResourceMapper.delete(wrapper);

                //删除角色对应的用户
                LambdaQueryWrapper<UserRoleEntity> wrapperUserRole = Wrappers.<UserRoleEntity>lambdaQuery()
                        .eq(UserRoleEntity::getRoleCode, roleCode);
                userRoleMapper.delete(wrapperUserRole);
        }
    }
}
